package org.zfes.snowier.common.monitor.mysql.dump;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.management.RuntimeErrorException;

import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.introspector.BeanAccess;
/**
 *  定时备份mysql
 * @author zhaoht
 *
 */
public class MysqlDumpRecover {
	
	
	private Integer dumpPeriod=60*2;
	private String configFile="config/mysql-dump.yml";
	private MysqlDopsConfig dumpConfig;
	
	private ScheduledExecutorService scheduledThreadPool ;
	
	
	private static MysqlDumpRecover mysqlOps; 
	
	private MysqlDumpRecover(String configFile,boolean isFromOuter) {
		this.configFile=configFile;
		initConfig(isFromOuter);
		scheduledThreadPool = Executors.newScheduledThreadPool(1);
	}
	public static MysqlDumpRecover getInsFromInnerConfig(String configFile) {
        if (mysqlOps == null) {
            synchronized (MysqlDumpRecover.class) {
            	if (mysqlOps == null) {
            		mysqlOps = new MysqlDumpRecover(configFile,false);
                }
            }
        }
        return mysqlOps;
	}
	
	public static MysqlDumpRecover getInsFromOuterConfig(String configFile) {
        if (mysqlOps == null) {
            synchronized (MysqlDumpRecover.class) {
            	if (mysqlOps == null) {
            		mysqlOps = new MysqlDumpRecover(configFile,true);
                }
            }
        }
        return mysqlOps;
	}
	
	public  void startPeriodDump() {
		
		scheduledThreadPool.scheduleAtFixedRate(()->{
			
			dumpConfig.getInstances().forEach(dops->{
				try {//防止异常退出所有定时任务
					
					mysqldump(dops);
					
				}catch (Exception e) {
					e.printStackTrace();
				}
			});
		},  0L,dumpPeriod, TimeUnit.MINUTES);
		
		System.out.println("mysql-dump-Period-started.....");
	}
	
	public void doDump() {
		dumpConfig.getInstances().forEach(dops->{
			try {//防止异常退出所有定时任务
				
				mysqldump(dops);
				
			}catch (Exception e) {
				e.printStackTrace();
			}
		});
	}

	
	private void initConfig(boolean isFromOuter) {
		if(configFile==null||configFile.equals("")) {
			throw new RuntimeException("配置文件错误");
		}
		Yaml yaml = new Yaml(new Constructor(MysqlDopsConfig.class));
		yaml.setBeanAccess(BeanAccess.FIELD);
		MysqlDopsConfig config=null;
		if(isFromOuter) {
			//String path=PathUtil.getProjectPath()+File.separator+this.configFile;
			try {
				  FileInputStream in = new FileInputStream(new File(configFile));  
				  config=(MysqlDopsConfig)yaml.load(in);
				  in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}else{
			config=(MysqlDopsConfig)yaml.load(MysqlDumpRecover.class.getClassLoader().getResourceAsStream(this.configFile));
		}
		if(config==null) {
			throw new RuntimeException("配置文件错误");
		}
		this.dumpConfig=config;
		this.dumpPeriod=dumpConfig.getDumpPeriod()==null?60*12:dumpConfig.getDumpPeriod();
		if(this.dumpPeriod<1) {
			throw new RuntimeException("dumpPeriod 时间跨度配置太短了");
		}
	}


	public  static long mysqldump(MysqlDops dops) {
		long a=System.currentTimeMillis();
		String mysqldumpPath=dops.getMysqldumpPath();
		
		String resultFilePath=dops.getResultFilePath();
		File saveFile = new File(resultFilePath);
		if (!saveFile.exists()) {// 如果目录不存在
			saveFile.mkdirs();// 创建文件夹
		}
		if (!resultFilePath.endsWith(File.separator)) {
			resultFilePath = resultFilePath + File.separator;
		}
		if (!mysqldumpPath.endsWith(File.separator)) {
			mysqldumpPath = mysqldumpPath + File.separator;
		}
		
		String dateString = new SimpleDateFormat("yyyy_MMdd_HH_mm_ss").format(new Date());
		String resultFile =dops.getResultFilePath()+ dops.getIp().replace(".", "_") +"_"+ dops.getDatabaseName() +"_"+ dateString +".sql";
		
		//备份数据库，控制台执行命令格式
		// mysqldump -h127.0.0.1 -P3306 -uroot -proot databackup> d：\ xxxx.sql
		try{
			Runtime rt = Runtime.getRuntime();
			Process process;
			if(isWindows()) {
				 process = rt.exec("cmd /c "+mysqldumpPath+File.separator+"mysqldump"+" -h"+ dops.getIp() +" -P"+ dops.getPort() +" -u"+ dops.getUsername() +" -p"+ dops.getPassword() +" "+dops.getDatabaseName()+"  --single-transaction ––skip-add-locks --skip-lock-tables >"+ resultFile);
			}else {
				//利用whereis命令查看mysqldump命令所在路径.如：whereis mysqldump
				 String[] cmd=new String[]{"/bin/bash ","-c ",mysqldumpPath+File.separator+"mysqldump"+" -h"+ dops.getIp() +" -P"+ dops.getPort() +" -u"+ dops.getUsername() +" -p"+ dops.getPassword() +" "+dops.getDatabaseName()+"   --single-transaction  ––skip-add-locks --skip-lock-tables>"+ resultFile};
				  process =rt.exec(cmd);
			}
			
			if (process.waitFor() == 0) {// 0 表示线程正常终止。
				long b=(System.currentTimeMillis()-a)/1000;
		    	  System.out.println("["+dops.getDatabaseName()+"]"+"数据备份完成，耗时："+ b +"秒");
                return b;
            }else {
            	 System.out.println("备份失败----1----");
            	return -1L;
            }
		}catch(Exception e){
			System.out.println("备份失败----。2----");
			e.printStackTrace();
		   return -1L;
		} 

	}
	
	  public static long recover(MysqlDops dops) {
		  long a=System.currentTimeMillis();
		  System.out.println("导入数据开始......");
		 
		  String mysqlPath=dops.getMysqlPath();
			if (!mysqlPath.endsWith(File.separator)) {
				mysqlPath = mysqlPath + File.separator;
			}
			
          String loginCommand = new StringBuffer()
        		  .append(mysqlPath)
        		  .append("mysql -h").append(dops.getIp())
        		  .append(" -u").append(dops.getUsername())
        		  .append(" -p").append(dops.getPassword())  
        		  .append(" -P").append(dops.getPort())
        		  .toString(); 
          
         
          String switchCommand = new StringBuffer().append("use ").append(dops.getDatabaseName()).toString();  
         
          String importCommand = new StringBuffer(" source ").append(dops.getResourceSQLFile()).toString();  

         String[] cmdarray = new String[] {loginCommand, switchCommand, importCommand};
         Runtime runtime = Runtime.getRuntime();  
         Process process;
		try {
			 process = runtime.exec(cmdarray[0]);
			 java.io.OutputStream os = process.getOutputStream();  
	         OutputStreamWriter writer = new OutputStreamWriter(os);  
	         writer.write(cmdarray[1] + "\r\n" + cmdarray[2]); 
	         writer.flush();  
	         writer.close();  
	         os.close();
	         System.out.println("导入数据结束......");
	         return (System.currentTimeMillis()-a)/1000;
		} catch (Exception e) {
			System.out.println("导入数据：数据导入失败。。。。。。");
			e.printStackTrace();
			return -1L;
		}  
		 
         
	  }


		private  static boolean isWindows() {
			return System.getProperties().getProperty("os.name").toUpperCase().indexOf("WINDOWS") != -1;
		}
	
	
}
